package com.zy;

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.input.structured.StructuredPrompt;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.output.structured.Description;
import dev.langchain4j.service.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

/**
 * @program: AI_langchain4j
 * @description: Ai Service的高级功能
 * @author: zy
 * @create: 2025-06-29 09:43
 */
public class _10_AiServiceAdvance {

   static String apiKey = System.getenv("OPEN_AI_KEY");

   static OpenAiChatModel model = OpenAiChatModel.builder()
            .apiKey(apiKey)
            .modelName("deepseek-chat")
            .baseUrl(   "https://api.deepseek.com"    )    //deepseek的API地址
            .logRequests(true)
            .logResponses(true)
            .build();

    //带系统提示词和用户提示词的Ai服务。  提供翻译(语言可指定), 给文章写总结
    static class Ai_service_with_system_and_user_messages_example{
        interface TranslatorService{
            @SystemMessage(    "你是{{language}}的专业翻译")
            @UserMessage("请翻译以下文本: {{text}}")
            String translate(@V("text") String text, @V("language") String language     );

            @SystemMessage("总结用户的消息为{{n}}个关键点.")
            List<String> summarize(   @UserMessage String text, @V("n") int n );
        }

        public static void main(String[] args) {
            //通过动态代理机制生成 Ai Service的代理类对象
            TranslatorService translatorService= AiServices.create(TranslatorService.class,  model );
            //String answer= translatorService.translate("你好，我是张三", "法语");
           // System.out.println(answer);

            String text="nemonefish are common inhabitants of coral reefs from the Indian Ocean to the western Pacific, feeding on plants, algae, plankton and ani\u0002mals such as mollusks and small crustaceans. Their small size, bright colors and absence of spines, sharp fins, barbs or spikes make them easy prey for the eels, sharks and other predators that rove the reef. When threatened, their principal means of defense is to dash between the tentacles of their host anemone, from whose poisonous sting they are protected by a thick layer of mucus covering their scales. In turn, the anemone benefits from its colorful tenants who chase off unwelcome intruders, such as grazing butterflyfish.";
            List<String> answer2= translatorService.summarize(text, 4);
            answer2.forEach(System.out::println);
        }
    }

    ////////////////////////////////////根据用户消息判定它的情绪
    static class Sentiment_Extracting_Ai_Service_Example{
        enum Sentiment{
            //情绪词的枚举
            POSITIVE, NEGATIVE, NEUTRAL
        }
        interface SentimentAnalyzerService{
            //情绪分析器
            @UserMessage("请分析{{it}}的情绪")
            Sentiment analyzeSentiment(@V("it") String text);

            @UserMessage("以下的句子{{it}}是否为正向情绪?")
            boolean isPositive(@V("it") String text);

            @UserMessage("以下的句子{{it}}是否为负向情绪?")
            boolean isNegative(@V("it") String text);
        }

        public static void main(String[] args) {
            SentimentAnalyzerService sentimentAnalyzerService= AiServices.create(SentimentAnalyzerService.class,  model );
            String text="I love you";
            boolean answer= sentimentAnalyzerService.isPositive(text);
            System.out.println(answer);

            Sentiment sentiment= sentimentAnalyzerService.analyzeSentiment( text );
            System.out.println(sentiment);
        }
    }

    ///////////////////////////酒店评论的AI分析服务
    static class Hotel_Review_Ai_Service_Example{
        //1. 设定评论类别的枚举
        public enum IssueCategory{
            MAINTENANCE_ISSUE, SERVICE_ISSUE,COMFORT_ISSUE,  FACILITY_ISSUE, CLEANLINESS_ISSUE, LOCATION_ISSUE,CHECK_IN_OUT_ISSUE,OVERALL_EXPERIENCE_ISSUE,EONNECTIVEITY_ISSUE
        }
        interface HotelReviewIssueAnalyzerService{
            @UserMessage("请分析以下的评论: {{review}}")
            List<IssueCategory> analyzeIssue(@V("review") String review);
        }

        public static void main(String[] args) {
            HotelReviewIssueAnalyzerService hotelReviewIssueAnalyzerService= AiServices.create(HotelReviewIssueAnalyzerService.class,  model );
            //String review="酒店的地理位置非常便利。它位于市中心，周围有许多著名景点和购物中心，交通十分方便。我可以步行前往钟楼、鼓楼等古迹，也可以乘坐地铁前往其他景点。这对于第一次来到西安的游客来说非常方便。\n" +
//                    "酒店的房间非常舒适。房间面积宽敞，装修简洁时尚。床铺柔软舒适，让人能够在疲惫的旅程后得到充分休息。房间内还配备有现代化的设施，包括高清电视、免费Wi-Fi和咖啡机等。这些设施的完善使得我的入住体验更加愉快。\n" +
//                    "酒店提供的早餐也非常出色。他们提供了丰富多样的食物选择，包括西式早餐和中式精美点心。我特别喜欢他们的汤面，口感醇厚，味道美味。酒店还提供了24小时的客房服务，可以满足客人的各种需求。\n" +
//                    "在员工方面，酒店的服务态度非常好。无论是前台接待员还是客房服务员，他们总是微笑着迎接客人，并且乐于解答各种问题。他们专业的素质和热情的服务让我感到宾至如归。\n" +
//                    "酒店还提供了一系列的休闲设施。我在入住期间使用了健身房和游泳池。健身房设备先进齐全，游泳池水质清澈，环境优雅。这使得我的旅途不仅仅是出差或旅游，同时也是一个放松身心的机会。\n" +
//                    "在西安欢朋希尔顿入住体验中，我对酒店的各个方面都非常满意。他们提供了舒适的房间、出色的早餐、周到的服务以及完善的休闲设施。如果你计划到西安旅行或商务出差，我强烈推荐选择西安欢朋希尔顿作为你的下榻之地。你一定会度过一个愉快而难忘的入住体验。";
            String review="Our stay at hotel was a mixed experience. The location was perfect, just a stone's throw away \" +\n" +
                    "                    \"from the beach, which made our daily outings very convenient. The rooms were spacious and well-decorated, \" +\n" +
                    "                    \"providing a comfortable and pleasant environment. However, we encountered several issues during our \" +\n" +
                    "                    \"stay. The air conditioning in our room was not functioning properly, making the nights quite uncomfortable. \" +\n" +
                    "                    \"Additionally, the room service was slow, and we had to call multiple times to get extra towels. Despite the \" +\n" +
                    "                    \"friendly staff and enjoyable breakfast buffet, these issues significantly impacted our stay.";
                    List<IssueCategory> answer= hotelReviewIssueAnalyzerService.analyzeIssue(review);
            answer.forEach(System.out::println);
        }
    }

    ///////////////////////////////////////////抽取数字服务/////////////////
    static class Number_Extracting_Ai_Service_Example {
        interface NumberExtractor {
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            int extractInt(@V("it") String text);
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            float extractFloat(@V("it") String text);
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            BigDecimal extractBigDecimal(@V("it") String text);
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            long extractLong(@V("it") String text);
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            BigInteger extractBigInteger(@V("it") String text);
            @UserMessage("请从以下文本中抽取数字:{{it}}")
            double extractDouble(@V("it") String text);
        }

        public static void main(String[] args) {
            NumberExtractor numberExtractor= AiServices.create(NumberExtractor.class,  model );
            String text="The price of the room is 1000.00 dollars.";
            int answer= numberExtractor.extractInt(text);
            System.out.println(answer);
            float answer2= numberExtractor.extractFloat(text);
            System.out.println(answer2);
            BigDecimal answer3= numberExtractor.extractBigDecimal(text);
            System.out.println(answer3);
        }
    }

    //////////////////////////抽取时间和日期
    static class Date_and_Time_Extracting_AI_Service_Example {
        interface DateTimeExtractor {
            @UserMessage("Extract date from {{it}}")
            LocalDate extractDateFrom(String text);
            @UserMessage("Extract time from {{it}}")
            LocalTime extractTimeFrom(String text);
            @UserMessage("Extract date and time from {{it}}")
            LocalDateTime extractDateTimeFrom(String text);
        }

        public static void main(String[] args) {
            DateTimeExtractor extractor = AiServices.create(DateTimeExtractor.class, model);
            //String text = "The tranquility pervaded the evening of 1968, just fifteen minutes shy of midnight,"
             //       + " following the celebrations of Independence Day.";
            String text="1968年的那个夜晚，在国庆节庆祝活动之后，距离午夜还有十五分钟，宁静弥漫在四周。";

            LocalDate date = extractor.extractDateFrom(text);
            System.out.println(date); // 1968-07-04

            LocalTime time = extractor.extractTimeFrom(text);
            System.out.println(time); // 23:45

            LocalDateTime dateTime = extractor.extractDateTimeFrom(text);
            System.out.println(dateTime); // 1968-07-04T23:45
        }
    }

    ///////////////////////抽取POJO对象
    static class POJO_Extracting_AI_Service_Example {
        //POJO类
        static class Person {
            @Description("first name of a person")
            // you can add an optional description to help an LLM have a better understanding
            private String firstName;
            private String lastName;
            private LocalDate birthDate;
            private String gender;

            @Override
            public String toString() {
                return "Person{" +
                        "firstName='" + firstName + '\'' +
                        ", lastName='" + lastName + '\'' +
                        ", birthDate=" + birthDate +
                        ", gender='" + gender + '\'' +
                        '}';
            }
        }

        interface PersonExtractor {
            @UserMessage("Extract a person from the following text: {{it}}")
            Person extractPersonFrom(String text);
        }

        public static void main(String[] args) {
            //因为此时的目标数据是一个复杂的对象， 要将复杂的对象变为json来完成转换， 所以要配置这个Model
            String apiKey = System.getenv("OPEN_AI_KEY");

            OpenAiChatModel model = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("deepseek-chat")
                    .baseUrl(   "https://api.deepseek.com"    )    //deepseek的API地址
                    .logRequests(true)
                    //.logResponses(true)
                    .responseFormat(   "json")
                    .strictJsonSchema(   true  )
                    .timeout(    Duration.ofSeconds(60)  )
                    .build();
            PersonExtractor extractor= AiServices.create( PersonExtractor.class,  model   );
            String text="In 1968, amidst the fading echoes of Independence Day, \"\n" +
                    "                    + \"a child named lilly arrived under the calm evening sky. \"\n" +
                    "                    + \"This newborn, bearing the surname Doe, marked the start of a new journey.";
            Person person=extractor.extractPersonFrom(text);
            System.out.println(person);
        }
    }

    //////////////////////////////////////从一段话，抽取信息形成一个订单(订单系统 )
    static class OrderPOJO_Extracting_AI_Service_Example {

        static class OrderItem{
            @Description("菜品名称")
            private String fname;
            @Description("数量")
            private int count;

            @Override
            public String toString() {
                return "OrderItem{" +
                        "fname='" + fname + '\'' +
                        ", count=" + count +
                        '}';
            }
        }
        static class Orders{
            @Description("订单项集合")
            private List<OrderItem> items;
            @Description("送餐地址")
            private String address;
            @Description("联系电话")
            private String phone;
            @Description("附言")
            private String note;
            @Description("收餐人名")
            private String name;

            @Override
            public String toString() {
                return "Orders{" +
                        "items=" + items +
                        ", address='" + address + '\'' +
                        ", phone='" + phone + '\'' +
                        ", note='" + note + '\'' +
                        ", name='" + name + '\'' +
                        '}';
            }
        }


        interface OrdersExtractor {
            @UserMessage("请从信息中抽取出订单详情: {{it}}")
            Orders extractOrdersFrom(String text);
        }

        public static void main(String[] args) {
            //因为此时的目标数据是一个复杂的对象， 要将复杂的对象变为json来完成转换， 所以要配置这个Model
            String apiKey = System.getenv("OPEN_AI_KEY");

            OpenAiChatModel model = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("deepseek-chat")
                    .baseUrl(   "https://api.deepseek.com"    )    //deepseek的API地址
                    .logRequests(true)
                    //.logResponses(true)
                    .responseFormat(   "json")
                    .strictJsonSchema(   true  )
                    .timeout(    Duration.ofSeconds(60)  )
                    .build();
            OrdersExtractor extractor= AiServices.create( OrdersExtractor.class,  model   );
            String text="请给湖南工学院顺枫公寓B6旷心怡送个餐, 一份辣椒炒肉，一份炖鸡，两瓶可乐，两份白米饭, 我的联系电话153858589432, 附言: 请不要让我等太久";
            Orders orders=extractor.extractOrdersFrom(   text );
            System.out.println(orders);
        }

    }

    /////////////////////////////////////// 将 prompt提示词与AI service结合: 用户提供菜名和原料，生成对应的菜的制作流程
    static class POJO_With_Prompt_Example {
        static class Recipe{
            @Description("显示的标题，最多5个字")
            private String title;
            @Description("对菜品一段短的描述,最多2句话")
            private String description;
            @Description("制作步骤,每一步用10个词描述即可")
            private List<String > steps;
            @Description("制作时间, 单位: 分钟")
            private Integer time;

            @Override
            public String toString() {
                return "Recipe{" +
                        "title='" + title + '\'' +
                        ", description='" + description + '\'' +
                        ", steps=" + steps +
                        ", time=" + time +
                        '}';
            }
        }
        @StructuredPrompt({
                "create a recipe of a {{dish}} that can be prepared using only {{ingredients}}. ",
                "Structure your answer in the following way:",
                "Recipe name:....",
                "Description:...",
                "Preparation time:....",
                "Required ingredients:....",
                "Instructions:...."
        })
        static class CreateRecipePrompt{
            String dish;
            List<String> ingredients;

            CreateRecipePrompt(String dish, List<String> ingredients) {
                this.dish = dish;
                this.ingredients = ingredients;
            }
        }
        interface Chef{
            Recipe createRecipeFrom( String... ingredients  );
            Recipe createRecipe( CreateRecipePrompt prompt   );
        }
        public static void main(String[] args) {
            String apiKey = System.getenv("OPEN_AI_KEY");

            OpenAiChatModel model = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("deepseek-chat")
                    .baseUrl(   "https://api.deepseek.com"    )    //deepseek的API地址
                    .logRequests(true)
                    //.logResponses(true)
                    .responseFormat(   "json")
                    .strictJsonSchema(   true  )
                    .timeout(    Duration.ofSeconds(60)  )
                    .build();

            Chef chef= AiServices.create( Chef.class,  model   );
            Recipe recipe= chef.createRecipeFrom(   "小米辣","青椒","五花肉","大蒜","蚝油","酱油","食用盐");
            System.out.println(recipe);

            CreateRecipePrompt prompt=new CreateRecipePrompt("宫保鸡丁", List.of("鸡","青椒","猪肉","大蒜","蚝油","酱油","食用盐"));
            Recipe recipe2= chef.createRecipe(   prompt );
            System.out.println(   recipe2 );
        }
    }

    /////////////////////////带记忆的Ai 服务
    // 1. memory的类型: message, token
    static class ServiceWithMemory_Example{
        interface Assistant{
            String chat(String message);
        }

        public static void main(String[] args) {
            //基于消息messagewindow的记忆
            ChatMemory chatMemory= MessageWindowChatMemory.withMaxMessages( 1000);
            Assistant assistant= AiServices.builder(  Assistant.class )
                    .chatModel(   model )
                    .chatMemory( chatMemory  )
                    .build();
            String answer= assistant.chat("你好，我是张三, 我是一名大三的学生，我的专业是计算机科学与技术。我学习过java, 数据库，spring data jpa, AI, langchain4j, spring boot等技术。我喜欢学习新的技术，并且喜欢和其他同学交流。我希望能和大家一起学习，一起进步。");
            System.out.println(answer);
            String answer2= assistant.chat("请给我一些就业提示。");
            System.out.println(answer2);
        }

    }

    /////////////////////////////////区分用户id的带记忆的Ai 服务
    static class ServiceWithMemory_Example2 {
        interface Assistant {
            String chat(@MemoryId int memoryId, @UserMessage String message);
        }

        public static void main(String[] args) {
            //基于消息messagewindow的记忆
            ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(1000);
            Assistant assistant = AiServices.builder(Assistant.class)
                    .chatModel(model)
                    .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(1000))
                    .build();
            String a1 = assistant.chat(1, "你好，我是旷心怡，我是一名大三的学生，我的专业是计算机科学与技术。我学习过java, 数据库，spring data jpa, AI, langchain4j, spring boot等技术。我喜欢学习新的技术，并且喜欢和其他同学交流。我希望能和大家一起学习，一起进步。");
            System.out.println(a1);
            String a2 = assistant.chat(2, "我是李牛吉,我是大数据专业的大三学生。");
            System.out.println(a2);

            String a3 = assistant.chat(1, "请给我一些就业提示。");
            System.out.println(a3);

            String a4 = assistant.chat(2, "请给我一些就业提示。");
            System.out.println(a4);



        }
    }

}
